import { MockMethod } from 'vite-plugin-mock'
import { faker } from '@faker-js/faker/locale/zh_CN'
// 修改导入，使用 ApiResponseUtil 替代 ApiResponse
import { ApiResponseUtil, PageResult } from '../../src/model/common-model'
import { DeployEnvironment, DeployStatus, DeployStep } from '../../src/model/deploy-model'
import type { DeployStepStatus, DeployRecord } from '../../src/model/deploy-model'

// 生成模拟步骤数据
const generateSteps = (status: DeployStatus, isFrontend = true) => {
  const steps = [
    {
      step: DeployStep.UPLOAD,
      status: DeployStatus.SUCCESS,
      message: '上传成功',
      startTime: faker.date.recent().toISOString(),
      endTime: faker.date.recent().toISOString()
    },
    {
      step: DeployStep.EXTRACT,
      status: DeployStatus.SUCCESS,
      message: '解压成功',
      startTime: faker.date.recent().toISOString(),
      endTime: faker.date.recent().toISOString()
    },
    {
      step: DeployStep.COPY_CONFIG,
      status: DeployStatus.SUCCESS,
      message: '配置文件已拷贝',
      startTime: faker.date.recent().toISOString(),
      endTime: faker.date.recent().toISOString()
    }
  ]

  // 根据项目类型添加不同的步骤
  if (isFrontend) {
    steps.push(
      {
        step: DeployStep.NPM_INSTALL,
        status: DeployStatus.SUCCESS,
        message: '依赖安装成功',
        startTime: faker.date.recent().toISOString(),
        endTime: faker.date.recent().toISOString()
      },
      {
        step: DeployStep.NPM_BUILD,
        status: DeployStatus.SUCCESS,
        message: '项目构建成功',
        startTime: faker.date.recent().toISOString(),
        endTime: faker.date.recent().toISOString()
      }
    )
  } else {
    steps.push({
      step: DeployStep.RESTART,
      status: DeployStatus.SUCCESS,
      message: '服务重启成功',
      startTime: faker.date.recent().toISOString(),
      endTime: faker.date.recent().toISOString()
    })
  }

  steps.push({
    step: DeployStep.COMPLETE,
    status: DeployStatus.SUCCESS,
    message: '部署完成',
    startTime: faker.date.recent().toISOString(),
    endTime: faker.date.recent().toISOString()
  })

  // 根据部署状态修改步骤状态
  if (status === DeployStatus.PROCESSING) {
    // 随机选择一个进行中的步骤
    const processingIndex = Math.floor(Math.random() * (steps.length - 1)) + 1
    steps[processingIndex].status = DeployStatus.PROCESSING
    steps[processingIndex].message = '正在执行...'
    steps[processingIndex].endTime = ''

    // 将后续步骤设为等待
    for (let i = processingIndex + 1; i < steps.length; i++) {
      steps[i].status = DeployStatus.PENDING
      steps[i].message = '等待中'
      steps[i].startTime = ''
      steps[i].endTime = ''
    }
  } else if (status === DeployStatus.FAILED) {
    // 随机选择一个失败的步骤
    const failedIndex = Math.floor(Math.random() * (steps.length - 1)) + 1
    steps[failedIndex].status = DeployStatus.FAILED
    steps[failedIndex].message = '执行失败: ' + faker.lorem.sentence()

    // 将后续步骤设为等待
    for (let i = failedIndex + 1; i < steps.length; i++) {
      steps[i].status = DeployStatus.PENDING
      steps[i].message = '等待中'
      steps[i].startTime = ''
      steps[i].endTime = ''
    }
  } else if (status === DeployStatus.PENDING) {
    // 所有步骤置为待执行
    for (let i = 0; i < steps.length; i++) {
      steps[i].status = DeployStatus.PENDING
      steps[i].message = '等待中'
      steps[i].startTime = ''
      steps[i].endTime = ''
    }
  }

  return steps
}

// 生成模拟日志
const generateLog = (status: DeployStatus) => {
  let log = '=== 部署开始 ===\n'
  log += `[${faker.date.recent().toISOString()}] 开始上传项目包\n`
  log += `[${faker.date.recent().toISOString()}] 项目包上传成功, 大小: ${faker.number.int({ min: 1, max: 50 })}MB\n`
  log += `[${faker.date.recent().toISOString()}] 开始解压项目包\n`
  log += `[${faker.date.recent().toISOString()}] 解压完成, 路径: /var/www/html/app\n`
  log += `[${faker.date.recent().toISOString()}] 开始拷贝配置文件\n`
  log += `[${faker.date.recent().toISOString()}] 配置文件拷贝成功\n`
  
  if (status === DeployStatus.FAILED) {
    log += `[${faker.date.recent().toISOString()}] 执行npm install\n`
    log += `[${faker.date.recent().toISOString()}] 错误: npm ERR! code ENOENT\n`
    log += `[${faker.date.recent().toISOString()}] 错误: npm ERR! syscall open\n`
    log += `[${faker.date.recent().toISOString()}] 错误: npm ERR! path /package.json\n`
    log += `[${faker.date.recent().toISOString()}] 错误: npm ERR! errno -2\n`
    log += `[${faker.date.recent().toISOString()}] 错误: npm ERR! enoent ENOENT: no such file or directory, open '/package.json'\n`
    log += `[${faker.date.recent().toISOString()}] 部署失败: 无法找到package.json文件\n`
    log += '=== 部署失败 ===\n'
  } else if (status === DeployStatus.PROCESSING) {
    log += `[${faker.date.recent().toISOString()}] 执行npm install\n`
    log += `[${faker.date.recent().toISOString()}] 安装依赖中...\n`
  } else if (status === DeployStatus.SUCCESS) {
    log += `[${faker.date.recent().toISOString()}] 执行npm install\n`
    log += `[${faker.date.recent().toISOString()}] 依赖安装成功\n`
    log += `[${faker.date.recent().toISOString()}] 执行npm run build\n`
    log += `[${faker.date.recent().toISOString()}] 项目构建成功\n`
    log += `[${faker.date.recent().toISOString()}] 部署完成\n`
    log += '=== 部署成功 ===\n'
  }
  
  return log
}

// 推进部署进度（模拟）
const advanceDeployment = (deploy: DeployRecord) => {
  // 仅对 pending / processing 的部署推进
  if (deploy.status !== DeployStatus.PROCESSING && deploy.status !== DeployStatus.PENDING) return

  const steps = deploy.steps
  const nowIso = new Date().toISOString()

  // 若整体处于 PENDING，立即启动第一个待执行步骤并切换为 PROCESSING（不做节流）
  if (deploy.status === DeployStatus.PENDING) {
    const firstPending = steps.findIndex((s) => s.status === DeployStatus.PENDING)
    if (firstPending !== -1) {
      steps[firstPending].status = DeployStatus.PROCESSING
      steps[firstPending].startTime = nowIso
      steps[firstPending].endTime = '' as any
      steps[firstPending].message = '正在执行...'
      deploy.status = DeployStatus.PROCESSING
      deploy.log = (deploy.log || '') + `[${nowIso}] 开始步骤: ${steps[firstPending].step}\n`
      console.debug(`[mock][advanceDeployment] ${deploy.id} -> start ${steps[firstPending].step}, status=${deploy.status}`)
    } else {
      // 没有等待中的步骤则直接完成
      deploy.status = DeployStatus.SUCCESS
      deploy.log = (deploy.log || '') + `[${nowIso}] 部署完成\n=== 部署成功 ===\n`
      console.debug(`[mock][advanceDeployment] ${deploy.id} -> completed with no pending steps`)
    }
    deploy.updateTime = nowIso
    return
  }

  // 对 processing 态做节流：每3秒推进一次
  const last = new Date(deploy.updateTime).getTime()
  if (Date.now() - last < 3000) return

  const processingIndex = steps.findIndex((s) => s.status === DeployStatus.PROCESSING)

  if (processingIndex !== -1) {
    // 当前步骤完成
    steps[processingIndex].status = DeployStatus.SUCCESS
    steps[processingIndex].endTime = nowIso
    steps[processingIndex].message = steps[processingIndex].message?.includes('正在执行') ? '已完成' : (steps[processingIndex].message || '已完成')
    deploy.log = (deploy.log || '') + `[${nowIso}] 步骤完成: ${steps[processingIndex].step}\n`

    // 进入下一步或完成
    if (processingIndex + 1 < steps.length) {
      steps[processingIndex + 1].status = DeployStatus.PROCESSING
      steps[processingIndex + 1].startTime = nowIso
      steps[processingIndex + 1].endTime = '' as any
      steps[processingIndex + 1].message = '正在执行...'
      deploy.log += `[${nowIso}] 开始步骤: ${steps[processingIndex + 1].step}\n`
      console.debug(`[mock][advanceDeployment] ${deploy.id} -> finish ${steps[processingIndex].step}, start ${steps[processingIndex + 1].step}`)
    } else {
      deploy.status = DeployStatus.SUCCESS
      deploy.log = (deploy.log || '') + `[${nowIso}] 部署完成\n=== 部署成功 ===\n`
      console.debug(`[mock][advanceDeployment] ${deploy.id} -> all steps finished, status=success`)
    }
  } else {
    // 没有processing则尝试启动第一个等待中的步骤
    const pendingIndex = steps.findIndex((s) => s.status === DeployStatus.PENDING)
    if (pendingIndex !== -1) {
      steps[pendingIndex].status = DeployStatus.PROCESSING
      steps[pendingIndex].startTime = nowIso
      steps[pendingIndex].endTime = '' as any
      steps[pendingIndex].message = '正在执行...'
      deploy.log = (deploy.log || '') + `[${nowIso}] 开始步骤: ${steps[pendingIndex].step}\n`
      console.debug(`[mock][advanceDeployment] ${deploy.id} -> start ${steps[pendingIndex].step}`)
    } else {
      // 没有等待中的步骤，标记完成
      deploy.status = DeployStatus.SUCCESS
      deploy.log = (deploy.log || '') + `[${nowIso}] 部署完成\n=== 部署成功 ===\n`
      console.debug(`[mock][advanceDeployment] ${deploy.id} -> no processing/pending, set success`)
    }
  }

  deploy.updateTime = nowIso
}

// 模拟部署数据 - 直接使用确定的数组而不是map方法，确保数据一定存在
const deploys: DeployRecord[] = [
  {
    id: 'deploy-1',
    projectId: 'proj-1',
    projectName: '测试项目A',
    environment: DeployEnvironment.DEVELOPMENT,
    status: DeployStatus.SUCCESS,
    version: '1.0.0',
    steps: generateSteps(DeployStatus.SUCCESS, true),
    log: generateLog(DeployStatus.SUCCESS),
    createTime: new Date().toISOString(),
    updateTime: new Date().toISOString()
  },
  {
    id: 'deploy-2',
    projectId: 'proj-2',
    projectName: '测试项目B',
    environment: DeployEnvironment.TESTING,
    status: DeployStatus.PROCESSING,
    version: '2.1.0',
    steps: generateSteps(DeployStatus.PROCESSING, true),
    log: generateLog(DeployStatus.PROCESSING),
    createTime: new Date().toISOString(),
    updateTime: new Date().toISOString()
  },
  {
    id: 'deploy-3',
    projectId: 'proj-1',
    projectName: '测试项目A',
    environment: DeployEnvironment.PRODUCTION,
    status: DeployStatus.FAILED,
    version: '1.0.5',
    steps: generateSteps(DeployStatus.FAILED, true),
    log: generateLog(DeployStatus.FAILED),
    createTime: new Date().toISOString(),
    updateTime: new Date().toISOString()
  },
  {
    id: 'deploy-4',
    projectId: 'proj-3',
    projectName: '测试项目C',
    environment: DeployEnvironment.DEVELOPMENT,
    status: DeployStatus.PENDING,
    version: '0.9.0',
    steps: generateSteps(DeployStatus.PENDING, false),
    log: generateLog(DeployStatus.PENDING),
    createTime: new Date().toISOString(),
    updateTime: new Date().toISOString()
  },
  {
    id: 'deploy-5',
    projectId: 'proj-2',
    projectName: '测试项目B',
    environment: DeployEnvironment.PRODUCTION,
    status: DeployStatus.SUCCESS,
    version: '2.0.0',
    steps: generateSteps(DeployStatus.SUCCESS, false),
    log: generateLog(DeployStatus.SUCCESS),
    createTime: new Date().toISOString(),
    updateTime: new Date().toISOString()
  }
];

// 添加更多随机生成的部署记录
Array.from({ length: 25 }).forEach((_, index) => {
  const id = `deploy-${index + 6}`
  const projectId = `proj-${Math.floor(Math.random() * 20) + 1}`
  const environment = [
    DeployEnvironment.DEVELOPMENT, 
    DeployEnvironment.TESTING, 
    DeployEnvironment.PRODUCTION
  ][Math.floor(Math.random() * 3)]
  
  const status = [
    DeployStatus.SUCCESS,
    DeployStatus.PROCESSING,
    DeployStatus.FAILED,
    DeployStatus.PENDING
  ][Math.floor(Math.random() * 4)]
  
  const isFrontend = Math.random() > 0.5
  
  deploys.push({
    id,
    projectId,
    projectName: faker.company.name() + ' 项目',
    environment,
    status,
    version: `${faker.number.int({ min: 1, max: 9 })}.${faker.number.int({ min: 0, max: 9 })}.${faker.number.int({ min: 0, max: 9 })}`,
    steps: generateSteps(status, isFrontend),
    log: generateLog(status),
    createTime: faker.date.past().toISOString(),
    updateTime: faker.date.recent().toISOString()
  });
});

export default [
  // 获取部署列表
  {
    url: '/api/deployments',  
    method: 'get',
    response: ({ query }) => {
      // 在列表查询时推进进行中的部署（模拟后台推进）
      deploys.forEach((d) => advanceDeployment(d))
      // 兼容多种分页参数命名：page/pageNum，page_size/pageSize
      const rawPage = (query as any).page ?? (query as any).pageNum ?? 1
      const rawPageSize = (query as any).page_size ?? (query as any).pageSize ?? 10
      const page = parseInt(rawPage as any, 10)
      const pageSize = parseInt(rawPageSize as any, 10)
      const { status, environment, projectId, projectName } = query as any
      
      let filteredDeploys = [...deploys]
      
      // 根据查询条件过滤
      if (status) {
        filteredDeploys = filteredDeploys.filter(item => item.status === status)
      }
      
      if (environment) {
        filteredDeploys = filteredDeploys.filter(item => item.environment === environment)
      }
      
      if (projectId) {
        filteredDeploys = filteredDeploys.filter(item => item.projectId === projectId)
      }
      
      if (projectName) {
        const q = String(projectName).toLowerCase()
        filteredDeploys = filteredDeploys.filter(item => item.projectName?.toLowerCase().includes(q))
      }
      
      // 计算分页
      const start = (Number(page) - 1) * Number(pageSize)
      const end = start + Number(pageSize)
      const pageData = filteredDeploys.slice(start, end)
      
      return ApiResponseUtil.success<PageResult<DeployRecord>>({
        list: pageData,
        total: filteredDeploys.length,
        pageNum: Number(page),
        pageSize: Number(pageSize)
      })
    }
  },
  
  // 获取部署详情
  {
    url: '/api/deployments/:id',  
    method: 'get',
    response: ({ query, params }) => {
      const { id } = params
      const deploy = deploys.find(item => item.id === id)
      
      if (!deploy) {
        return ApiResponseUtil.fail(404, '部署不存在')
      }
      // 在详情查询时推进一次（模拟）
      advanceDeployment(deploy)
      
      return ApiResponseUtil.success(deploy)
    }
  },
  
  // 创建部署
  {
    url: '/api/deployments',  
    method: 'post',
    response: ({ body }) => {
      const { projectId, environment, version } = body
      
      if (!projectId || !environment || !version) {
        return ApiResponseUtil.fail(400, '缺少必要参数')
      }
      
      const newDeploy = {
        id: `deploy-${deploys.length + 1}`,
        projectId,
        projectName: faker.company.name() + ' 项目',
        environment,
        status: DeployStatus.PROCESSING,
        version,
        steps: generateSteps(DeployStatus.PROCESSING),
        log: generateLog(DeployStatus.PROCESSING),
        createTime: new Date().toISOString(),
        updateTime: new Date().toISOString()
      }
      
      deploys.unshift(newDeploy)
      
      return ApiResponseUtil.success(newDeploy)
    }
  },
  
  // 获取部署日志
  {
    url: '/api/deployments/:id/logs',  
    method: 'get',
    response: ({ params, query }) => {
      const { id } = params
      const deploy = deploys.find(item => item.id === id)
      
      if (!deploy) {
        return ApiResponseUtil.fail(404, '部署不存在')
      }

      // 先推进一次部署（与详情/列表保持一致的推进节奏），再根据 from 返回增量日志
      const from = query?.from !== undefined ? parseInt(query.from, 10) : 0
      const prevLen = (deploy.log || '').length
      advanceDeployment(deploy)
      const logStr = deploy.log || ''
      const start = Number.isFinite(from) && from > 0 ? Math.min(from, logStr.length) : 0
      const slice = logStr.slice(start)
      // 调试输出，便于排查日志增量问题
      try {
        console.debug(`[mock][logs] ${id} from=${from} prevLen=${prevLen} currLen=${logStr.length} returned=${slice.length}`)
      } catch {}
      return ApiResponseUtil.success(slice)
    }
  },
  
  // 取消部署
  {
    url: '/api/deployments/:id/cancel',  
    method: 'post',
    response: ({ params }) => {
      const { id } = params
      const index = deploys.findIndex(item => item.id === id)
      
      if (index === -1) {
        return ApiResponseUtil.fail(404, '部署不存在')
      }
      
      if (deploys[index].status !== DeployStatus.PROCESSING) {
        return ApiResponseUtil.fail(400, '只能取消进行中的部署')
      }
      
      const nowIso = new Date().toISOString()
      deploys[index].status = DeployStatus.FAILED
      // 将当前进行中的步骤标记为失败，后续步骤设为等待
      const steps = deploys[index].steps
      const processingIndex = steps.findIndex(s => s.status === DeployStatus.PROCESSING)
      if (processingIndex !== -1) {
        steps[processingIndex].status = DeployStatus.FAILED
        steps[processingIndex].message = '已取消'
        steps[processingIndex].endTime = nowIso
        for (let i = processingIndex + 1; i < steps.length; i++) {
          steps[i].status = DeployStatus.PENDING
          steps[i].startTime = '' as any
          steps[i].endTime = '' as any
          steps[i].message = '等待中'
        }
      }
      deploys[index].log = (deploys[index].log || '') + `[${nowIso}] 部署已被用户取消\n=== 部署失败 ===\n`
      deploys[index].updateTime = nowIso
      
      return ApiResponseUtil.success(deploys[index])
    }
  },
  
  // 重试部署
  {
    url: '/api/deployments/:id/retry',  
    method: 'post',
    response: ({ params }) => {
      const { id } = params
      const index = deploys.findIndex(item => item.id === id)
      
      if (index === -1) {
        return ApiResponseUtil.fail(404, '部署不存在')
      }
      
      if (deploys[index].status !== DeployStatus.FAILED) {
        return ApiResponseUtil.fail(400, '只能重试失败的部署')
      }
      
      const oldDeploy = deploys[index]
      const newDeploy = {
        ...oldDeploy,
        id: `deploy-${deploys.length + 1}`,
        status: DeployStatus.PROCESSING,
        steps: generateSteps(DeployStatus.PROCESSING),
        log: generateLog(DeployStatus.PROCESSING),
        createTime: new Date().toISOString(),
        updateTime: new Date().toISOString()
      }
      
      deploys.unshift(newDeploy)
      
      return ApiResponseUtil.success(newDeploy)
    }
  }
] as MockMethod[]
